<template>
  <div class="x-select">
    <div
      ref="target"
      class="input"
      @click="toggle"
    >
      <input
        v-model="value"
        class="field"
        type="text"
        readonly
        :placeholder="placeholder"
        :class="{ multiple: isMultiple, focus: show, error: showError }"
      />
      <icon-font
        :name="equ === 'pc' ? 'form-arrow' : 'arrow-down'"
        class="arrow"
        :class="{ show, 'pc-arrow': equ === 'pc' }"
      />
      <span
        v-if="isMultiple && modelValue.length > 1"
        class="count"
      >
        +{{ modelValue.length }}
      </span>
    </div>
    <teleport to="body">
      <div
        v-if="show"
        ref="group"
      >
        <x-option-group
          :pos="style"
          @click.stop
        >
          <x-option
            v-for="x in options"
            :key="x.value"
            :checked="isMultiple ? (modelValue || []).includes(x.value) : modelValue === x.value"
            :label="x.name"
            @click.stop="handClick(x)"
          />
        </x-option-group>
      </div>
    </teleport>
  </div>
</template>

<script
  lang="ts"
  setup
  name="XSelect"
>
import { useClickAway, useScrollParent, useEventListener } from '@/hooks/useEvent'
import { equ } from '../../../../package-env'
// if (equ )

// eslint-disable-next-line vue/require-prop-types
const props = defineProps(['modelValue', 'options', 'multiple', 'placeholder', 'error'])
const emit = defineEmits(['update:modelValue', 'change'])

const target = ref()
const group = ref()
const show = ref(false)
const style = ref({})

const isMultiple = computed(() => {
  const { multiple } = props
  return multiple !== undefined && multiple !== false
})

const value = computed(() => {
  const { modelValue, options } = props
  const v = !isMultiple.value ? modelValue : modelValue.length > 0 ? modelValue[0] : ''
  const item = options.find((n) => v === n.value)
  return item ? item.name : ''
})

const toggle = () => {
  if (show.value) {
    style.value = {}
    show.value = false
  } else {
    const { bottom, left, width } = target.value.getBoundingClientRect()
    style.value = { left: `${left}px`, top: `${bottom + 5}px`, width: `${width}px` }
    show.value = true
  }
}

const handClick = (item) => {
  let v
  if (isMultiple.value) {
    const { modelValue } = props
    const oldItem = modelValue.find((n) => n === item.value)
    v = oldItem !== undefined ? modelValue.filter((n) => n !== item.value) : modelValue.concat(item.value)
  } else {
    v = item.value
    show.value && toggle()
  }
  emit('update:modelValue', v)
  emit('change', v)
}

const showError = computed(() => {
  if (value.value !== '') {
    return false;
  }
  if (props.error && value.value === '') {
    return true;
  }
  if (typeof props.error === 'boolean') {
    return props.error;
  }
});

useClickAway([target, group], toggle)

const scrollParent = useScrollParent(target)

useEventListener('scroll', () => show.value && toggle(), { target: scrollParent })
</script>

<style
  scoped
  lang="scss"
>
.x-select {
  @apply relative w-full flex-1;

  .input {
    @apply relative w-full;

    .arrow {
      @apply absolute;
      top: 50%;
      right: 10px;
      font-size: 12px;
      margin-top: $select-arrow;
      /* transform: rotate(0deg); */
      transition: transform 0.3s;

      &.show {
        transform: rotate(-180deg);
      }
    }

    .pc-arrow {
      transform: scale(0.8);
      margin-top: calc($select-arrow - 1px);

      &.show {
        transform: rotate(-180deg) scale(0.8);
      }
    }

    .count {
      @apply absolute;
      top: calc(50% - 9px);
      right: 30px;
      border-radius: 15px;
      font-size: 10px;
      background: $select-count-bg;
      color: $select-count-color;
      padding: 0 8px;
    }
  }

  .field {
    @apply flex-1 w-full truncate;
    @include form-placeholder;
    background: $input-bg;
    color: $input-color;
    border-radius: 6px;
    font-size: $form-font-size;
    /* line-height: 17px; */
    padding: 9px 28px 9px 10px;
    resize: none;
    border-radius: 6px;
    outline: none;

    &.multiple {
      padding-right: 66px;
    }

    &.focus {
      @include select-focus;
    }
  }

  .error {
    box-shadow: $form-error;
  }
}
</style>
